# coding: utf-8
from app.modules.common.Errors import ServiceError
from app.modules.common.utils import FileUtil, JsonFileUtil, Jinja2Utils
from config import BaseConfig


def remove(menu_id, workspace='default'):
    # 1.读取menu, 把它搞成一个json对象, 失败就抛异常.
    menu_json = read_menu_to_json(workspace)

    # 2.找到上级ID,如果为空, 就在锁定在第一级, 否则就递归向下找
    removed_item = remove_item(menu_json, menu_id)

    if removed_item is None:
        raise ServiceError(
            u"删除失败,请确认菜单的ID是否正确, menu_id:%s" % menu_id)

    # 4.把这个内容dump成文本, 写入到目标文件中
    save_menu(menu_json.get('child'), workspace=workspace)


def remove_item(menu_json, menu_id):
    child_menu_list = menu_json.get('child')

    # 如果没有子节点, 直接返回None,代表未找到.
    if (child_menu_list is None) or isinstance(child_menu_list, basestring):
        return None

    for menu_item in child_menu_list:

        # 如果在兄弟节点里找到该menu,删除内容之后, 将被删内容返回.
        if menu_item.get('id') == menu_id:
            child_menu_list.remove(menu_item)
            return menu_item
        else:
            # 如果没有找到,则递归查询其子孙节点
            removed_menu_item = remove_item(menu_item, menu_id)

            # 子孙节点也没有, 继续遍历兄弟节点.
            if removed_menu_item is not None:
                return removed_menu_item

    return None


def update(path, parent_menu_id, menu_id, index, title, is_front, is_action,
           workspace='default'):
    if parent_menu_id == menu_id:
        raise ServiceError(
            u"更改失败,上下级ID不能相等, parent_menu_id:%s" % parent_menu_id)

    # 1.读取menu, 把它搞成一个json对象, 失败就抛异常.
    menu_json = read_menu_to_json(workspace)

    # 2.找到上级ID,如果为空, 就在锁定在第一级, 否则就递归向下找
    menu_item_json = find_item(menu_json, menu_id)

    is_update = False

    if menu_item_json is not None:
        is_update = True

    # 3.用当前的标题和path,覆盖到json内容中, 插入要求的位置.
    menu_item_json = merge_item(menu_item_json=menu_item_json, uuid=menu_id,
                                path=path,
                                title=title,
                                is_front=is_front, is_item=is_item)

    if is_update:
        remove_item(menu_json, menu_id)

    success = insert_menu_item(item=menu_json,
                               parent_menu_id=parent_menu_id,
                               index=index, target_item=menu_item_json)

    if not success:
        raise ServiceError(
            u"更改失败,请确认上级菜单的ID是否正确, parent_menu_id:%s" % parent_menu_id)

    # 4.把这个内容dump成文本, 写入到目标文件中
    save_menu(menu_json.get('child'), workspace=workspace)


def read_menu_to_json(worlspace):
    menu_path = BaseConfig.WORKSPACES[worlspace] + "/src/config/menu.js"
    if not FileUtil.file_exists(menu_path):
        raise ServiceError(u"尝试修改menu失败: %s 文件不存在" % menu_path)

    menu_list = JsonFileUtil.match_and_decode(path=menu_path,
                                              match=r"(const menu = )([\w\W]*])(;)([\w\W]*)",
                                              replace="\\2")

    return {'front': True, 'path': '/', 'id': 'ROOT', 'name': 'ROOT',
            'child': menu_list}


def find_item(item, uuid):
    # 根据id匹配当前节点, 如果没找到就递归它的子节点.
    if item.get('id') == uuid:
        return item

    if (item.get('child') is None) or (
            isinstance(item.get('child'), basestring)):
        return None

    for child_item in item.get('child'):
        target_item = find_item(child_item, uuid=uuid)
        if target_item is not None:
            return target_item

    return None


def merge_item(menu_item_json, uuid, path, title='新建菜单', is_front=True,
               is_item=False):
    if menu_item_json is None:
        menu_item_json = {}

    menu_item_json['id'] = uuid
    menu_item_json['name'] = title
    menu_item_json['front'] = is_front
    menu_item_json['path'] = path

    return menu_item_json


def insert_menu_item(item, parent_menu_id, index, target_item):
    if item is None:
        return False

    print item.get('id')

    if item.get('id') == parent_menu_id:
        if item.get('child') is None or isinstance(
                item.get('child'), basestring):
            item['child'] = []
        child_item_list = item.get('child')

        index = min(index, len(child_item_list))
        # 顶层菜单
        child_item_list.insert(index, target_item)
        return True

    # 如果当前节点不匹配, 就递归查找其子节点
    if item.get('child') is None or isinstance(
            item.get('child'), basestring):
        return False

    child_item_list = item.get('child')

    for child_item in child_item_list:
        has_find = insert_menu_item(item=child_item,
                                    parent_menu_id=parent_menu_id, index=index,
                                    target_item=target_item)
        if has_find:
            return True

    return False


def save_menu(menu_json, workspace):
    json_content = JsonFileUtil.dump(menu_json)

    menu_path = BaseConfig.WORKSPACES[workspace] + "/src/config/menu.js"
    if not FileUtil.file_exists(menu_path):
        raise ServiceError(u"尝试修改menu失败: %s 文件不存在" % menu_path)

    FileUtil.replace_content(menu_path,
                             match=r"(const menu = )([\w\W]*])(;)([\w\W]*)",
                             replace=r"\g<1>%s\g<3>\g<4>" % json_content)


# update(path=u'/aaa', parent_menu_id=u'123456', menu_id=u'123456_1', index=3,
#        title=u'测试版本3_1',
#        is_front=True,
#        is_item=True)

# remove(menu_id=u'8888x')
def recreate(menu_items, workspace='default'):
    menu_path = BaseConfig.WORKSPACES[workspace] + "/src/config/menu.json"

    menu_items = JsonFileUtil.load(menu_items)
    content = Jinja2Utils.render("menu.jinja2", {'items': menu_items})
    # 4. 写入文件
    FileUtil.write(menu_path, content)